<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>this规则一-默认绑定(This rule one - default binding)</title>
  <!-- 
  在JavaScript中，this关键字的行为受到多种规则的影响。其中，“默认绑定”（Default Binding）是最基本的规则之一。以下是对“默认绑定”规则的实现和总结说明：
  一、默认绑定的定义
  默认绑定: 是指当一个函数在全局作用域中被调用时，this的值指向全局对象。在浏览器环境中，全球对象是window，而在Node.js环境中，全球对象是global。

  二、默认绑定的实现
  1. 全局上下文：
    - 在全局作用域中，如果不在任何对象的上下文中调用函数，this将指向全局对象。
    function showThis() {
      console.log(this);
    }
    showThis(); // 在浏览器中输出: Window {...}
  2. 在非严格模式下：
    - 在非严格模式下，调用一个普通函数时，this会指向全局对象。
    function showGlobal() {
      console.log(this); // 输出: Window {...}
    }

    showGlobal();
  3. 在严格模式下：
    - 在严格模式下（通过在文件或函数顶部添加'use strict';），this的值将是undefined。
    'use strict';
    function showThisStrict() {
      console.log(this); // 输出: undefined
    }

    showThisStrict();

  三、默认绑定的注意事项
  - 函数调用：只有在函数被直接调用时，才会使用默认绑定。如果函数是作为对象的方法被调用，this将指向该对象。
    
  - 箭头函数：箭头函数不使用默认绑定，它会捕获定义时的this值。因此，在箭头函数中，this的值与外部上下文相同。
    const obj = {
      name: 'Alice',
      greet: function() {
        console.log(this.name); // 输出: Alice
        const innerFunc = function() {
          console.log(this); // 默认绑定，输出: Window {...} (在非严格模式下)
        };
        innerFunc();
        
        const arrowFunc = () => {
          console.log(this.name); // 输出: Alice
        };
        arrowFunc();
      }
    };

    obj.greet();

  四、总结

  - 默认绑定是指在全局上下文中调用函数时，this指向全局对象（在浏览器中是window）。
  - 在非严格模式下，this指向全局对象，而在严格模式下，this的值为undefined。
  - 理解默认绑定规则有助于更好地掌握this的行为，避免在使用函数时出现意外的上下文问题。
   -->
</head>
<body>

  <script>
    // 默认绑定
    // 1. 在严格模式下：
    // "use strict"
    // function showThisStrict() {
    //   console.log("在严格模式下：", this); // 输出: undefined
    // }

    // showThisStrict();
    
    // 2. 在非严格模式下：
    function showGlobal() {
      console.log("在非严格模式下：", this); // 输出: Window {...}
    }

    showGlobal();

    // 3. 对象方法中的this
    // 3.1 但是独立调用函数时，this指向全局对象
    const obj = {
      name: 'Alice',
      greet: function() {
        console.log("this.name", this.name); // 输出: Alice
        const innerFunc = function() {
          console.log(this); // 默认绑定，输出: Window {...} (在非严格模式下)
        };
        innerFunc();
      }
    }

    obj.greet();

    // 3.2 函数定义在对象中, 但是独立调用
    const obj2 = {
      name: 'Bob',
      greet: function() {
        console.log("greet", this); 
      }
    }

    const baz = obj2.greet
    baz(); // 输出: Window {...} (在非严格模式下)

    // 4. 函数作为构造函数调用
    function Person(name) {
      this.name = name;
      this.greet = function() {
        console.log("Person", this); // 输出: Person {...}
      };
    }

    const person = new Person('Charlie');
    person.greet();

    // 5. 函数作为回调函数调用
    function callFunc(func) {
      func(); // 输出: Window {...} (在非严格模式下)
    }

    callFunc(function() {
      console.log("callFunc", this); 
    });

    // 6. 高阶函数
    function higherOrderFunc(callback) {
      callback();
    }

    higherOrderFunc(obj.greet);
    
  </script>
  
</body>
</html>